/*/////////////////////////////////////////////////////////////////////////////////
/// An
///    ___   ____ ___ _____ ___  ____
///   / _ \ / ___|_ _|_   _/ _ \|  _ \
///  | | | | |  _ | |  | || | | | |_) |
///  | |_| | |_| || |  | || |_| |  _ <
///   \___/ \____|___| |_| \___/|_| \_\
///                              File
///
/// Copyright (c) 2008-2009 Ismail TARIM <ismail@royalspor.com> and the Ogitor Team
//
//This program is free software; you can redistribute it and/or modify it under
//the terms of the GNU Lesser General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT
//ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
//FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License along with
//this program; if not, write to the Free Software Foundation, Inc., 59 Temple
//Place - Suite 330, Boston, MA 02111-1307, USA, or go to
//http://www.gnu.org/copyleft/lesser.txt.
////////////////////////////////////////////////////////////////////////////////*/

#pragma once

namespace Ogre
{
    class Terrain;
}

namespace Ogitors
{
#define BRUSH_DATA_SIZE 128

    typedef std::vector<CPagedTerrainEditor*> TerrainRows;
    typedef std::vector<TerrainRows> TerrainVector;

class OgitorExport CPagedTerrainManager : public CBaseEditor, public CTerrainEditor, public Ogre::ManualResourceLoader
{
    friend class CPagedTerrainManagerFactory;
public:
    static OgitorsPropertyDefMap propertyDefs;

    /// Returns the Factory associated with this object
	static CBaseEditorFactory   *getFactory();
    /// Returns the Factory associated with this object can be overridden
	virtual CBaseEditorFactory  *getFactoryDynamic();

    void             setWorldSize(const Ogre::Real& value, bool display);
    Ogre::Real       getWorldSize();
    void             setMapSize(const int& value, bool display);
    int              getMapSize();

    virtual void     setSelectedImpl(bool bSelected);
    virtual void     processParameters(Ogre::NameValuePairList &params);
    virtual bool     load();
    virtual bool     unLoad();
	virtual void     getObjectProperties(Ogre::NameValuePairList &retList);
	virtual bool	 setupPropertiesWnd(bool present);
  	virtual bool     handleCustomFunction(int BIND_ID, Ogre::String val);
    void             removePage(CPagedTerrainEditor *page);


	/// General Purpose Update Function Used By OgitorsRoot Override for Descendants
	virtual bool                 postSceneUpdate(Ogre::SceneManager *SceneMngr, Ogre::Camera *Camera, Ogre::RenderWindow *RenderWindow);
	/// General Purpose Update Function Used By SCBEditorRoot Override for Descendants
	virtual bool                 update(float timePassed);
	/// This function is called when user right clicks a property to get that property specific popup menu
	/// returns false if no menu present (Disabled Menu Items has a "D" prefix where Enabled Menu Items have "E" prefix
	virtual bool                 getObjectContextMenu(UTFStringVector &menuitems);
    /// This function is called when user selects a menuitem from ContextMenu
	virtual void                 onObjectContextMenu(int menuresult);
    /// Overridden by Editor Objects to Import Object Dependant Properties
    virtual void                 restore(Ogre::NameValuePairList &retList);
    virtual Ogre::AxisAlignedBox getAABB();
    Ogre::Frustum               *getDecalFrustum() {return m_DecalFrustum;};

    virtual bool                 isTerrainType() {return true;};
    virtual CTerrainEditor*      getTerrainEditor() {return dynamic_cast<CTerrainEditor*>(this);};
    /// CTerrainEditor OVERRIDES
    virtual bool	             hitTest(Ogre::Ray camRay, Ogre::Vector3 *result = NULL);
    virtual void			     newTerrain(int size, float scaleX, float scaleY, int SplatSize, int LightMapSize, int ColourMapSize, int CellSpan) {};
    virtual void                 loadTerrain(Ogre::String FilesDir,int size, float scaleX, float scaleY, int SplatSize, int LightMapSize, int ColourMapSize, int CellSpan, Ogre::StringVector splats ) {};
    virtual void                 fillSplattingInfo() {};
    virtual PGHeightFunction    *getHeightFunction() {return 0;};
    virtual Ogre::AxisAlignedBox getSize() {return getAABB();};
    virtual Ogre::StringVector   getMaterialNames();

    virtual void setMousePosition(Ogre::Ray camRay);
    virtual void setBrush(const std::string& brush);
    virtual void setBrushSize(unsigned int size);
    virtual void setBrushOrientation(Ogre::Radian orient) {};
    virtual void setBrushIntensity(float intensity);
    virtual void setEditMode(unsigned int mode);
    virtual void setTexture(const std::string& texture);
    virtual void setColour(const Ogre::ColourValue& colour) {};
    virtual void setEditDirection(bool inverse) {m_EditDirection = inverse;};
    virtual bool isSelected();


    virtual void startEdit();
    virtual void stopEdit();

protected:
    TerrainVector    m_Pages; 
    Ogre::SceneNode *m_DecalNode;
    Ogre::Frustum   *m_DecalFrustum;
    Ogre::TexturePtr m_DecalTexture;
    CPagedTerrainEditor *m_CurrentTerrainPage;

    unsigned int     m_Columns;
    unsigned int     m_Rows;
    int              m_OriginX;
    int              m_OriginY;
    Ogre::Real       m_WorldSize;
    int              m_MapSize;

    float           *m_BrushData;


	CPagedTerrainManager();
	virtual     ~CPagedTerrainManager();

    virtual void loadResource(Ogre::Resource* resource);
    bool _getEditRect(Ogre::Vector3& editpos, Ogre::Rect& brushrect, Ogre::Rect& maprect, int size);
    void _splat(CPagedTerrainEditor *editor, Ogre::Terrain *terrain, Ogre::Vector3 &editpos, float timePassed);
    void _deform(Ogre::Terrain *terrain, Ogre::Vector3 &editpos, float timePassed);
    void _smooth(Ogre::Terrain *terrain, Ogre::Vector3 &editpos, float timePassed);
};

class OgitorExport CPagedTerrainManagerFactory: public CBaseEditorFactory
{
public:
  CPagedTerrainManagerFactory();
  virtual ~CPagedTerrainManagerFactory() {};
  virtual void Init();
  virtual bool CanInstantiate();
  virtual CBaseEditor *CreateObject(CBaseEditor **parent, Ogre::NameValuePairList &params);
};
}

